////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2017-2018 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxcawbioutil.cpp
/// @brief The class that implements input/output for AWB stats processor class.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "camxcawbioutil.h"
#include "camxhal3module.h"
#include "camxhal3metadatautil.h"
#include "camxmem.h"
#include "camxcsljumptable.h"
#include "camxhal3metadatautil.h"
#include "camxstatsdebuginternal.h"
#include "camxtitan17xdefs.h"
#include "camxtuningdatamanager.h"
// #include "camxstatscommon.h"
#include "camxtrace.h"
#include "camximagesensormoduledata.h"
#include "camximagesensordata.h"


CAMX_NAMESPACE_BEGIN


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::CAWBIOUtil
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CAWBIOUtil::CAWBIOUtil()
    : m_algoFlashEstimationState(AWBAlgoFlashEstimationInactive)
{
    CAMX_ENTRYEXIT(CamxLogGroupAWB);

    // Initialize default non-zero output
    m_outputs.illuminantType    = StatsIlluminantInvalid;
    m_outputs.state             = AWBAlgoStateInactive;
    m_outputs.mode              = AWBAlgoModeAuto;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::Initialize
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::Initialize(
    const StatsInitializeData* pInitializeData)
{
    CamxResult result = CamxResultSuccess;

    if (NULL == pInitializeData)
    {
        result = CamxResultEInvalidPointer;
    }

    if (CamxResultSuccess == result)
    {
        m_pNode             = pInitializeData->pNode;
        m_pDebugDataPool    = pInitializeData->pDebugDataPool;
        m_pStatsParser      = pInitializeData->pHwContext->GetStatsParser();
        m_pTuningManager    = pInitializeData->pTuningDataManager;
        m_inputs.cameraInfo = pInitializeData->cameraInfo;
        CAMX_ASSERT(m_pTuningManager != NULL);

        m_pNode->GetSensorModeData(&m_pSensorData);
        if (result != CamxResultSuccess)
        {
            CAMX_LOG_ERROR(CamxLogGroupAWB, "Error to get sensor mode result: %s", CamxResultStrings[result]);
        }
        else
        {
            m_pNode->GetIFEInputResolution(&m_pIFEInput);
        }

        // Get sensor static capability
        SensorModuleStaticCaps       sensorStaticCaps    = { 0 };
        HwContext*                   pHwContext          = pInitializeData->pHwContext;
        const ImageSensorModuleData* pSensorModuleData   =
            pHwContext->GetImageSensorModuleData(pInitializeData->pPipeline->GetCameraId());
        ImageSensorData*             pImageSensorData    = pSensorModuleData->GetSensorDataObject();

        pImageSensorData->GetSensorStaticCapability(&sensorStaticCaps, pInitializeData->pPipeline->GetCameraId());

        m_setInputs.statsSensorInfo.sensorActiveResWidth  = static_cast<UINT32>(sensorStaticCaps.activeArraySize.width);
        m_setInputs.statsSensorInfo.sensorActiveResHeight =  static_cast<UINT32>(sensorStaticCaps.activeArraySize.height);

    }

    if (CamxResultSuccess == result)
    {
        m_inputs.statsSession.Initialize(pInitializeData);
    }

    return result;
}



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::SetAWBBayerGrid
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID CAWBIOUtil::SetAWBBayerGrid(
    ParsedAWBBGStatsOutput* pBayerGridOutput,
    ISPAWBBGStatsConfig*    pStatsConfig,
    StatsBayerGrid*         pBayerGrid,
    StatsRectangle*         pBayerGridROI)
{
    BGBEConfig* pBGConfig = &pStatsConfig->AWBBGConfig;

    pBayerGrid->horizontalRegionCount       = pBGConfig->horizontalNum;
    pBayerGrid->verticalRegionCount         = pBGConfig->verticalNum;
    pBayerGrid->totalRegionCount            = pBGConfig->horizontalNum * pBGConfig->verticalNum;
    pBayerGrid->regionWidth                 = pStatsConfig->regionWidth;
    pBayerGrid->regionHeight                = pStatsConfig->regionHeight;
    pBayerGrid->bitDepth                    = static_cast<UINT16>(pBGConfig->outputBitDepth);


    pBayerGrid->flags.hasSatInfo            = pBayerGridOutput->flags.hasSatInfo;
    pBayerGrid->flags.usesY                 = pBayerGridOutput->flags.usesY;
    pBayerGrid->numValidRegions             = pBayerGridOutput->numROIs;

    pBayerGridROI->left                     = pBGConfig->ROI.left;
    pBayerGridROI->top                      = pBGConfig->ROI.top;
    pBayerGridROI->width                    = pBGConfig->ROI.width;
    pBayerGridROI->height                   = pBGConfig->ROI.height;

    if (NULL != pBayerGridOutput->GetChannelDataArray())
    {
        pBayerGrid->SetChannelDataArray(reinterpret_cast<StatsBayerGridChannelInfo*>(pBayerGridOutput->GetChannelDataArray()));
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupAWB, "BG data array NULL");
    }

    CAMX_TRACE_MESSAGE_F(CamxLogGroupAWB, "SetAWBBayerGrid: numvalid %d, totalreg %d, h %d, v %d", pBayerGrid->numValidRegions,
        pBayerGrid->totalRegionCount, pBayerGrid->horizontalRegionCount, pBayerGrid->verticalRegionCount);

    CAMX_LOG_VERBOSE(CamxLogGroupAWB, "SetAWBBayerGrid: numvalid %d, totalreg %d, h %d, v %d ROI:(%d %d %d %d)",
                     pBayerGrid->numValidRegions,
                     pBayerGrid->totalRegionCount,
                     pBayerGrid->horizontalRegionCount,
                     pBayerGrid->verticalRegionCount,
                     pBayerGridROI->left,
                     pBayerGridROI->top,
                     pBayerGridROI->width,
                     pBayerGridROI->height);

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::GetRequestNumber
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::GetRequestNumber(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoInputList*              pInputList)
{
    m_inputs.requestNumber                                              = pStatsProcessRequestDataInfo->requestId;
    pInputList->pAWBInputs[AWBInputTypeRequestNumber].inputType         = AWBInputTypeRequestNumber;
    pInputList->pAWBInputs[AWBInputTypeRequestNumber].pAWBInput         = &m_inputs.requestNumber;
    pInputList->pAWBInputs[AWBInputTypeRequestNumber].sizeOfAWBInput    = sizeof(UINT64);

    return CamxResultSuccess;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::GetStatistics
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::GetStatistics(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoInputList*              pInputList,
    BOOL                           processStatus)
{
    CAMX_UNREFERENCED_PARAM(pStatsProcessRequestDataInfo);
    CamxResult result = CamxResultSuccess;

    if (FALSE == processStatus)
    {
        m_inputs.statsBayerGrid.startupMode                        = StatisticsStartUpInvalid;
        pInputList->pAWBInputs[AWBInputTypeBGStats].inputType      = AWBInputTypeBGStats;
        pInputList->pAWBInputs[AWBInputTypeBGStats].pAWBInput      = &m_inputs.statsBayerGrid;
        pInputList->pAWBInputs[AWBInputTypeBGStats].sizeOfAWBInput = sizeof(StatsBayerGrid);
    }
    else
    {
        static const UINT GetProps[] = { PropertyIDParsedAWBBGStatsOutput, PropertyIDISPAWBBGConfig };
        static const UINT GerPropsLength = CAMX_ARRAY_SIZE(GetProps);
        VOID*             pData[GerPropsLength] = { 0 };
        UINT64            offsets[GerPropsLength] = { 0, m_pNode->GetStaticSettings()->maxPipelineDelay };

        m_pNode->GetDataList(GetProps, pData, offsets, GerPropsLength);

        CAMX_ASSERT_MESSAGE(NULL != pData[0], "PropertyIDParsedAWBBGStatsOutput not published!");
        CAMX_ASSERT_MESSAGE(NULL != pData[1], "PropertyIDISPAWBBGConfig not published!");

        ParsedAWBBGStatsOutput* pBGStats = reinterpret_cast<ParsedAWBBGStatsOutput*>(*static_cast<VOID**>(pData[0]));
        if (NULL != pBGStats && NULL != pBGStats->GetChannelDataArray() && NULL != pData[1])
        {
            // Save the BG stats inside core's input structure
            SetAWBBayerGrid(reinterpret_cast<ParsedAWBBGStatsOutput*>(*static_cast<VOID**>(pData[0])),
                reinterpret_cast<ISPAWBBGStatsConfig*>(pData[1]),
                &m_inputs.statsBayerGrid,
                &m_inputs.statsBayerGridROI);
        }
        else
        {
            CAMX_LOG_ERROR(CamxLogGroupAWB, "BG data array NULL");
            result = CamxResultEFailed;
        }

        if (CamxResultSuccess == result)
        {

            m_inputs.statsBayerGrid.startupMode = StatisticsStartUpValid;
            pInputList->pAWBInputs[AWBInputTypeBGStats].inputType = AWBInputTypeBGStats;
            pInputList->pAWBInputs[AWBInputTypeBGStats].pAWBInput = &m_inputs.statsBayerGrid;
            pInputList->pAWBInputs[AWBInputTypeBGStats].sizeOfAWBInput = sizeof(StatsBayerGrid);

            pInputList->pAWBInputs[AWBInputTypeBGStatsROI].inputType = AWBInputTypeBGStatsROI;
            pInputList->pAWBInputs[AWBInputTypeBGStatsROI].pAWBInput = &m_inputs.statsBayerGridROI;
            pInputList->pAWBInputs[AWBInputTypeBGStatsROI].sizeOfAWBInput = sizeof(StatsRectangle);

        }
    }

    // Indicating parsed stats are related to online BPSAWBBG stats
    m_isOffline = FALSE;
    pInputList->pAWBInputs[AWBInputTypeIsOffline].inputType = AWBInputTypeIsOffline;
    pInputList->pAWBInputs[AWBInputTypeIsOffline].pAWBInput = &m_isOffline;
    pInputList->pAWBInputs[AWBInputTypeIsOffline].sizeOfAWBInput = sizeof(BOOL);

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::PublishCrossProperty
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::PublishCrossProperty(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo)
{
    CamxResult result = CamxResultSuccess;

    // Publish AWB cross pipeline property for dual camera usecase.
    UINT64              requestId                                   = pStatsProcessRequestDataInfo->requestId;
    static const UINT   pWriteProps[]                               = { PropertyIDCrossAWBStats };
    const VOID*         pOutputData[CAMX_ARRAY_SIZE(pWriteProps)]   = { &requestId };
    UINT                pDataCount[CAMX_ARRAY_SIZE(pWriteProps)]    = { sizeof(requestId) };

    result = m_pNode->WriteDataList(pWriteProps, pOutputData, pDataCount, CAMX_ARRAY_SIZE(pWriteProps));
    CAMX_LOG_VERBOSE(CamxLogGroupAWB, "Published PropertyIDCrossAWBStats:%X for Req:%llu result:%d",
                     PropertyIDCrossAWBStats, requestId, result);

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::PublishPeerInfo
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::PublishPeerInfo(
    const StatsProcessRequestData*  pStatsProcessRequestDataInfo,
    VOID*                           pPeerInfo)
{
    CamxResult  result      = CamxResultSuccess;
    UINT64      requestId   = pStatsProcessRequestDataInfo->requestId;

    // Publish AWB cross pipeline property for dual camera usecase.
    static const UINT   pWriteProps[]                               = { PropertyIDAWBPeerInfo };
    const VOID*         pOutputData[CAMX_ARRAY_SIZE(pWriteProps)]   = { &pPeerInfo };
    UINT                pDataCount[CAMX_ARRAY_SIZE(pWriteProps)]    = { sizeof(VOID*) };

    result = m_pNode->WriteDataList(pWriteProps, pOutputData, pDataCount, CAMX_ARRAY_SIZE(pWriteProps));
    CAMX_LOG_VERBOSE(CamxLogGroupAWB, "Published PropertyIDAWBPeerInfo:%X with peer info:%p for Req:%llu result:%d",
                     PropertyIDAWBPeerInfo, pPeerInfo, requestId, result);

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::GetAECData
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::GetAECData(
    AWBAlgoInputList*              pInputList)
{
    CamxResult          result                  = CamxResultSuccess;
    static const UINT GetProps[]                = {PropertyIDAECFrameInfo};
    static const UINT GerPropsLength            = CAMX_ARRAY_SIZE(GetProps);
    VOID*             pData[GerPropsLength]     = { 0 };
    UINT64            offsets[GerPropsLength]   = { 0 };

    m_pNode->GetDataList(GetProps, pData, offsets, GerPropsLength);

    if (NULL == pData[0])
    {
        CAMX_LOG_ERROR(CamxLogGroupAWB, "PropertyIDAECFrameInfo is not published!");
        result = CamxResultEFailed;
    }
    else
    {
        Utils::Memset(&m_inputs.exposureInfo, 0, sizeof(m_inputs.exposureInfo));

        m_inputs.exposureInfo.luxIndex      = reinterpret_cast<AECFrameInformation*>(pData[0])->luxIndex;
        m_inputs.exposureInfo.AECSettled    = reinterpret_cast<AECFrameInformation*>(pData[0])->AECSettled;
        m_inputs.exposureInfo.frameDuration = reinterpret_cast<AECFrameInformation*>(pData[0])->frameDuration;

        pInputList->pAWBInputs[AWBInputTypeAECData].inputType = AWBInputTypeAECData;
        pInputList->pAWBInputs[AWBInputTypeAECData].pAWBInput = &m_inputs.exposureInfo;
        pInputList->pAWBInputs[AWBInputTypeAECData].sizeOfAWBInput = sizeof(m_inputs.exposureInfo);
        pInputList->inputCount++;
    }
    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::GetVendorTags
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::GetVendorTags(
    AWBAlgoInputList*              pInputList)
{
    CamxResult result = CamxResultSuccess;

    CAMX_ASSERT(NULL != pInputList);

    Utils::Memset(&m_inputs.vendorTagInputList, 0, sizeof(m_inputs.vendorTagInputList));

    for (UINT32 i = 0; i < m_vendorTagInputList.vendorTagCount; i++)
    {
        UINT32 tagId = m_vendorTagInputList.vendorTag[i].vendorTagId;

        static const UINT GetProps[]      = {tagId};
        static const UINT GerPropsLength          = CAMX_ARRAY_SIZE(GetProps);
        VOID*             pData[GerPropsLength]   = { 0 };
        UINT64            offsets[GerPropsLength] = { 0 };

        m_pNode->GetDataList(GetProps, pData, offsets, GerPropsLength);

        m_inputs.vendorTagInputList.vendorTag[i].pData       = pData[0];
        m_inputs.vendorTagInputList.vendorTag[i].vendorTagId = tagId;
        m_inputs.vendorTagInputList.vendorTag[i].dataSize    = static_cast<UINT32>(HAL3MetadataUtil::GetMaxSizeByTag(tagId));
        m_inputs.vendorTagInputList.vendorTag[i].appliedDelay = 0;

        if ((m_inputs.vendorTagInputList.vendorTag[i].pData != NULL) && (m_inputs.vendorTagInputList.vendorTag[i].dataSize > 0))
        {
            m_inputs.vendorTagInputList.vendorTagCount++;
        }
        else
        {
            CAMX_LOG_ERROR(CamxLogGroupAWB,
                           "Failed to retrieve input vendor tag data. Id: %u pData:%p dataSize:%u",
                           tagId,
                           m_inputs.vendorTagInputList.vendorTag[i].pData,
                           m_inputs.vendorTagInputList.vendorTag[i].dataSize);

            result = CamxResultEFailed;
            break;
        }
    }

    if (CamxResultSuccess == result)
    {
        pInputList->pAWBInputs[AWBInputTypeVendorTag].inputType = AWBInputTypeVendorTag;
        pInputList->pAWBInputs[AWBInputTypeVendorTag].pAWBInput = &m_inputs.vendorTagInputList;
        pInputList->pAWBInputs[AWBInputTypeVendorTag].sizeOfAWBInput = sizeof(m_inputs.vendorTagInputList);
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::GetDebugDataBuffer
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::GetDebugDataBuffer(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoInputList*              pInputList)
{
    UINT64      requestId   = pStatsProcessRequestDataInfo->requestId;
    DebugData*  pDebugData  = NULL;
    CamxResult  result      = CamxResultSuccess;

    // Only use debug data on the master camera
    if ((StatsAlgoRoleDefault   == pStatsProcessRequestDataInfo->cameraInfo.algoRole)   ||
        (StatsAlgoRoleMaster    == pStatsProcessRequestDataInfo->cameraInfo.algoRole))
    {
        result = StatsUtil::GetDebugDataBuffer(m_pDebugDataPool, requestId, PropertyIDDebugDataAWB, &pDebugData);
    }

    if ((CamxResultSuccess == result) && (NULL != pDebugData))
    {
        m_inputs.debugData.dataSize  = static_cast<UINT32>(pDebugData->size);
        m_inputs.debugData.pData     = pDebugData->pData;

        pInputList->pAWBInputs[AWBInputTypeDebugData].inputType         = AWBInputTypeDebugData;
        pInputList->pAWBInputs[AWBInputTypeDebugData].pAWBInput         = &m_inputs.debugData;
        pInputList->pAWBInputs[AWBInputTypeDebugData].sizeOfAWBInput    = sizeof(StatsDataPointer);
    }

    // Treat debug data failures as passive error - always return success
    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::GetChiStatsSession
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::GetChiStatsSession(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoInputList*              pInputList)
{
    m_inputs.statsSession.SetStatsProcessorRequestData(pStatsProcessRequestDataInfo);

    pInputList->pAWBInputs[AWBInputTypeStatsChiHandle].inputType      = AWBInputTypeStatsChiHandle;
    pInputList->pAWBInputs[AWBInputTypeStatsChiHandle].pAWBInput      = &m_inputs.statsSession;
    pInputList->pAWBInputs[AWBInputTypeStatsChiHandle].sizeOfAWBInput = sizeof(ChiStatsSession);

    return CamxResultSuccess;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::SetCameraInformation
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::SetCameraInformation(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoInputList*              pInputList,
    BOOL                           processStats)
{
    if (TRUE== processStats)
    {
        m_inputs.cameraInfo.algoRole   = pStatsProcessRequestDataInfo->cameraInfo.algoRole;
        m_inputs.cameraInfo.cameraId   = pStatsProcessRequestDataInfo->cameraInfo.cameraId;
        m_inputs.cameraInfo.cameraType = pStatsProcessRequestDataInfo->cameraInfo.cameraType;
    }
    pInputList->pAWBInputs[AWBInputTypeCameraInfo].inputType      = AWBInputTypeCameraInfo;
    pInputList->pAWBInputs[AWBInputTypeCameraInfo].pAWBInput      = &m_inputs.cameraInfo;
    pInputList->pAWBInputs[AWBInputTypeCameraInfo].sizeOfAWBInput = sizeof(StatsCameraInfo);

    return CamxResultSuccess;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::RetrieveSensorInfo
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::RetrieveSensorInfo(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoSetParamList*           pSetInputList)
{
    CAMX_UNREFERENCED_PARAM(pStatsProcessRequestDataInfo);

    CamxResult          result                  = CamxResultSuccess;
    StatsSensorInfo*    pSensorInfo             = &(m_setInputs.statsSensorInfo);
    static const UINT   GetProps[]              = { InputControlAETargetFpsRange, PropertyIDUsecaseLensInfo };
    static const UINT   GerPropsLength          = CAMX_ARRAY_SIZE(GetProps);
    VOID*               pData[GerPropsLength]   = { 0 };
    UINT64              offsets[GerPropsLength] = { 0, 0 };

    m_pNode->GetDataList(GetProps, pData, offsets, GerPropsLength);

    if ((NULL == pData[0]) || (NULL == pData[1]))
    {
        CAMX_LOG_ERROR(CamxLogGroupAWB,
                       "ControlAETargetFpsRange: %p or PropertyIDUsecaseLensInfo: % is not published!",
                       pData[0],
                       pData[1]);
        result = CamxResultEFailed;
    }
    else
    {
        FLOAT maxVal                      = static_cast<FLOAT>(reinterpret_cast<RangeINT32*>(pData[0])->max);
        pSensorInfo->currentFPS           = Utils::FloatToQNumber(maxVal, 256);
        pSensorInfo->fNumber              = reinterpret_cast<LensInfo*>(pData[1])->fNumber;
        pSensorInfo->maxFPS               = Utils::FloatToQNumber(static_cast<FLOAT>(m_pSensorData->maxFPS), 256);
        pSensorInfo->currentLinesPerFrame = static_cast<UINT32>(m_pSensorData->numLinesPerFrame);
        pSensorInfo->currentMaxLineCount  = static_cast<UINT32>(m_pSensorData->maxLineCount);
        pSensorInfo->maxGain              = static_cast<FLOAT>(m_pSensorData->maxGain);
        pSensorInfo->pixelClock           = static_cast<UINT32>(m_pSensorData->outPixelClock);
        pSensorInfo->pixelClockPerLine    = static_cast<UINT32>(m_pSensorData->numPixelsPerLine);
        pSensorInfo->sensorResWidth       = static_cast<UINT32>(m_pSensorData->resolution.outputWidth);
        pSensorInfo->sensorResHeight      = static_cast<UINT32>(m_pSensorData->resolution.outputHeight);

        /* In sum binning use cases, HVX will do the binning, Input to the IFE is different from the sensor.
        Stats modules need to calculate ROI's based on IFE's input*/
        if ((m_pIFEInput->resolution.width < pSensorInfo->sensorResWidth) ||
            (m_pIFEInput->resolution.height < pSensorInfo->sensorResHeight))
        {
            pSensorInfo->sensorResWidth  = m_pIFEInput->resolution.width;
            pSensorInfo->sensorResHeight = m_pIFEInput->resolution.height;
        }
        pSensorInfo->pixelSumFactor       = static_cast<UINT16>(m_pSensorData->binningTypeH);

        pSetInputList->pAWBSetParams[AWBSetParamTypeSensorInfo].setParamType        = AWBSetParamTypeSensorInfo;
        pSetInputList->pAWBSetParams[AWBSetParamTypeSensorInfo].pAWBSetParam        =
            static_cast<const VOID*>(&m_setInputs.statsSensorInfo);
        pSetInputList->pAWBSetParams[AWBSetParamTypeSensorInfo].sizeOfInputParam    = sizeof(StatsSensorInfo);
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::RetrieveManualWhiteBalanceInfo
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::RetrieveManualWhiteBalanceInfo(
    const StatsProcessRequestData*  pStatsProcessRequestDataInfo,
    AWBAlgoSetParamList*            pSetInputList)
{
    CAMX_UNREFERENCED_PARAM(pStatsProcessRequestDataInfo);

    CamxResult result = CamxResultSuccess;

    /// @todo (CAMX-138): After Manual WB has implemented, manual settings will be filled into m_setInputs.manualConfig
    /// structure here
    pSetInputList->pAWBSetParams[AWBSetParamTypeManualSettings].setParamType     = AWBSetParamTypeManualSettings;
    pSetInputList->pAWBSetParams[AWBSetParamTypeManualSettings].pAWBSetParam     =
        static_cast<const VOID*>(&m_setInputs.manualConfig);
    pSetInputList->pAWBSetParams[AWBSetParamTypeManualSettings].sizeOfInputParam = sizeof(AWBAlgoManualConfiguration);

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::RetrieveStatsWindowInfo
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::RetrieveStatsWindowInfo(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoSetParamList*           pSetInputList)
{
    CAMX_UNREFERENCED_PARAM(pStatsProcessRequestDataInfo);
    const StaticSettings* pStaticSettings       = HwEnvironment::GetInstance()->GetStaticSettings();
    static const UINT   GetProps[]              = { InputScalerCropRegion };
    static const UINT   GetPropsLength          = CAMX_ARRAY_SIZE(GetProps);
    VOID*               pData[GetPropsLength]   = { 0 };
    UINT64              offsets[GetPropsLength] = { 0 };
    CropWindow          HALCropWindow           = { 0 };
    CamxResult          result                  = CamxResultSuccess;
    FLOAT               widthRatio              = static_cast<FLOAT>(m_setInputs.statsSensorInfo.sensorResWidth) /
                                                                      (m_setInputs.statsSensorInfo.sensorActiveResWidth);
    FLOAT               heightRatio             = static_cast<FLOAT>(m_setInputs.statsSensorInfo.sensorResHeight) /
                                                                      (m_setInputs.statsSensorInfo.sensorActiveResHeight);

    CAMX_ASSERT(pStaticSettings != NULL);

    m_pNode->GetDataList(GetProps, pData, offsets, GetPropsLength);

    if (NULL != pData[0])
    {
        HALCropWindow    = (*reinterpret_cast<CropWindow*>(pData[0]));
    }

    if (HALCropWindow.left + HALCropWindow.width > m_setInputs.statsSensorInfo.sensorActiveResWidth)
    {
        CAMX_LOG_WARN(CamxLogGroupAWB, "Wrong input: HALCropWindow left(%d) + width(%d) > Active Array width(%d)",
            HALCropWindow.left, HALCropWindow.width, m_setInputs.statsSensorInfo.sensorActiveResWidth);
        HALCropWindow.width = m_setInputs.statsSensorInfo.sensorActiveResWidth - HALCropWindow.left;
    }
    if (HALCropWindow.top + HALCropWindow.height > m_setInputs.statsSensorInfo.sensorActiveResHeight)
    {
        CAMX_LOG_WARN(CamxLogGroupAWB, "Wrong input: HALCropWindow top(%d) + height(%d) > Active Array height(%d)",
            HALCropWindow.top, HALCropWindow.height, m_setInputs.statsSensorInfo.sensorActiveResHeight);
        HALCropWindow.height = m_setInputs.statsSensorInfo.sensorActiveResHeight - HALCropWindow.top;
    }

    if (HALCropWindow.width != 0 &&
        HALCropWindow.height != 0)
    {
        // mapping crop window to CAMIF size from Sensor Active pixel size
        m_setInputs.statsWindowInfo.cropWindow.width  = Utils::RoundFLOAT(HALCropWindow.width * widthRatio);
        m_setInputs.statsWindowInfo.cropWindow.height = Utils::RoundFLOAT(HALCropWindow.height * heightRatio);
        m_setInputs.statsWindowInfo.cropWindow.left   = Utils::RoundFLOAT(HALCropWindow.left * widthRatio);
        m_setInputs.statsWindowInfo.cropWindow.top    = Utils::RoundFLOAT(HALCropWindow.top * heightRatio);
    }
    else
    {
        m_setInputs.statsWindowInfo.cropWindow.left   = 0;
        m_setInputs.statsWindowInfo.cropWindow.top    = 0;
        m_setInputs.statsWindowInfo.cropWindow.width  = m_setInputs.statsSensorInfo.sensorResWidth;
        m_setInputs.statsWindowInfo.cropWindow.height = m_setInputs.statsSensorInfo.sensorResHeight;
        CAMX_LOG_WARN(CamxLogGroupAWB, "Wrong input: HALCropWindow width,height=%d %d",
        HALCropWindow.width, HALCropWindow.height);
    }

    pSetInputList->pAWBSetParams[AWBSetParamTypeStatsWindow].setParamType       = AWBSetParamTypeStatsWindow;
    pSetInputList->pAWBSetParams[AWBSetParamTypeStatsWindow].pAWBSetParam       =
        static_cast<const VOID*>(&m_setInputs.statsWindowInfo);
    pSetInputList->pAWBSetParams[AWBSetParamTypeStatsWindow].sizeOfInputParam   = sizeof(StatsWindowInfo);

    CAMX_LOG_VERBOSE(CamxLogGroupAWB,
        "Stats crop window: HALCrop %d %d %d %d, AdjustCrop %d %d %d %d, SensorRes %d %d, ActiveArray %d %d, w h ratio %f %f",
        HALCropWindow.left,
        HALCropWindow.top,
        HALCropWindow.width,
        HALCropWindow.height,
        m_setInputs.statsWindowInfo.cropWindow.left,
        m_setInputs.statsWindowInfo.cropWindow.top,
        m_setInputs.statsWindowInfo.cropWindow.width,
        m_setInputs.statsWindowInfo.cropWindow.height,
        m_setInputs.statsSensorInfo.sensorResWidth,
        m_setInputs.statsSensorInfo.sensorResHeight,
        m_setInputs.statsSensorInfo.sensorActiveResWidth,
        m_setInputs.statsSensorInfo.sensorActiveResHeight,
        widthRatio,
        heightRatio);

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::RetrieveCalibrationData
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::RetrieveCalibrationData(
    const StatsProcessRequestData*  pStatsProcessRequestDataInfo,
    AWBAlgoSetParamList*            pSetInputList)
{
    /// @todo (CAMX-151): Implement calibration data input, including:
    /// Illuminants calibration
    /// Geometrical disparity calibration
    /// LED calibration

    CamxResult      result = CamxResultSuccess;
    HwCameraInfo    cameraInfo;

    result = HwEnvironment::GetInstance()->GetCameraInfo(pStatsProcessRequestDataInfo->cameraInfo.cameraId, &cameraInfo);

    if (CamxResultSuccess == result)
    {
        FillIlluminantCalibrationFactor(&cameraInfo.pSensorCaps->OTPData.WBCalibration[0],
                        &m_setInputs.illuminantsCalibrationFactor);

        /// @note Retrieved illuminants calibration data should be filled into m_setInputs.illuminantsCalibrationFactor
        pSetInputList->pAWBSetParams[AWBSetParamTypeIlluminantsCalibrationFactor].setParamType      =
            AWBSetParamTypeIlluminantsCalibrationFactor;
        pSetInputList->pAWBSetParams[AWBSetParamTypeIlluminantsCalibrationFactor].pAWBSetParam      =
            static_cast<const VOID*>(&m_setInputs.illuminantsCalibrationFactor);
        pSetInputList->pAWBSetParams[AWBSetParamTypeIlluminantsCalibrationFactor].sizeOfInputParam  =
            sizeof(AWBAlgoIlluminantsCalibrationFactor);

        /// @note Retrieved geometrical calibration data should be filled into m_setInputs.geometricalDisparityCalibration
        pSetInputList->pAWBSetParams[AWBSetParamTypeGeometricalDisparityCalibration].setParamType       =
            AWBSetParamTypeGeometricalDisparityCalibration;
        pSetInputList->pAWBSetParams[AWBSetParamTypeGeometricalDisparityCalibration].pAWBSetParam       =
            static_cast<const VOID*>(&m_setInputs.geometricalDisparityCalibration);
        pSetInputList->pAWBSetParams[AWBSetParamTypeGeometricalDisparityCalibration].sizeOfInputParam   =
            sizeof(AWBAlgoGeometricalDisparityCalibration);

        /// @note Retrieved LED calibration data should be filled into m_setInputs.LEDCalibrationDataInput
        pSetInputList->pAWBSetParams[AWBSetParamTypeLEDCalibrationData].setParamType        =
            AWBSetParamTypeLEDCalibrationData;
        pSetInputList->pAWBSetParams[AWBSetParamTypeLEDCalibrationData].pAWBSetParam        =
            static_cast<const VOID*>(&m_setInputs.LEDCalibrationDataInput);
        pSetInputList->pAWBSetParams[AWBSetParamTypeLEDCalibrationData].sizeOfInputParam    =
            sizeof(StatsLEDCalibrationDataInput);
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupAWB, "Failed to get OTP data, result: %d", result);
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::RetrieveAWBMode
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::RetrieveAWBMode(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoSetParamList*           pSetInputList)
{
    CAMX_UNREFERENCED_PARAM(pStatsProcessRequestDataInfo);

    CamxResult              result                  = CamxResultSuccess;
    static const UINT       GetProps[]              = { InputControlAWBMode };
    static const UINT       GetPropsLength          = CAMX_ARRAY_SIZE(GetProps);
    VOID*                   pData[GetPropsLength]   = { 0 };
    UINT64                  offsets[GetPropsLength] = { 0 };

    m_pNode->GetDataList(GetProps, pData, offsets, GetPropsLength);

    if (NULL == pData[0])
    {
        CAMX_LOG_ERROR(CamxLogGroupAWB, "InputControlAWBMode is not published!");
        result = CamxResultEFailed;
    }
    else
    {
        switch (*reinterpret_cast<ControlAWBModeValues*>(pData[0]))
        {
            case ControlAWBModeOff:
                m_setInputs.algoMode = AWBAlgoModeOff;
                break;
            case ControlAWBModeAuto:
                m_setInputs.algoMode = AWBAlgoModeAuto;
                break;
            case ControlAWBModeIncandescent:
                m_setInputs.algoMode = AWBAlgoModeIncandescent;
                break;
            case ControlAWBModeFluorescent:
                m_setInputs.algoMode = AWBAlgoModeFluorescent;
                break;
            case ControlAWBModeWarmFluorescent:
                m_setInputs.algoMode = AWBAlgoModeWarmFluorescent;
                break;
            case ControlAWBModeDaylight:
                m_setInputs.algoMode = AWBAlgoModeDaylight;
                break;
            case ControlAWBModeCloudyDaylight:
                m_setInputs.algoMode = AWBAlgoModeCloudyDaylight;
                break;
            case ControlAWBModeTwilight:
                m_setInputs.algoMode = AWBAlgoModeTwilight;
                break;
            case ControlAWBModeShade:
                m_setInputs.algoMode = AWBAlgoModeShade;
                break;
            default:
                m_setInputs.algoMode = AWBAlgoModeAuto;
                break;
        }

        m_outputs.mode = m_setInputs.algoMode;

        pSetInputList->pAWBSetParams[AWBSetParamTypeWhiteBalanceMode].setParamType = AWBSetParamTypeWhiteBalanceMode;
        pSetInputList->pAWBSetParams[AWBSetParamTypeWhiteBalanceMode].pAWBSetParam =
            static_cast<const VOID*>(&m_setInputs.algoMode);
        pSetInputList->pAWBSetParams[AWBSetParamTypeWhiteBalanceMode].sizeOfInputParam = sizeof(AWBAlgoMode);

    }
    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::RetrieveSceneMode
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::RetrieveSceneMode(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoSetParamList*           pSetInputList)
{
    CAMX_UNREFERENCED_PARAM(pStatsProcessRequestDataInfo);

    CamxResult              result                  = CamxResultSuccess;
    static const UINT       GetProps[]              = { InputControlSceneMode };
    static const UINT       GerPropsLength          = CAMX_ARRAY_SIZE(GetProps);
    VOID*                   pData[GerPropsLength]   = { 0 };
    UINT64                  offsets[GerPropsLength] = { 0 };

    m_pNode->GetDataList(GetProps, pData, offsets, GerPropsLength);

    if (NULL == pData[0])
    {
        CAMX_LOG_VERBOSE(CamxLogGroupAWB, "InputControlSceneMode is not published!");
    }
    else
    {
        m_setInputs.sceneMode = *reinterpret_cast<UINT32*>(pData[0]);
        if (TRUE == HwEnvironment::GetInstance()->GetStaticSettings()->ignoreSceneMode)
        {
            m_setInputs.sceneMode = ControlSceneModeDisabled;
        }

        pSetInputList->pAWBSetParams[AWBSetParamTypeSceneMode].setParamType = AWBSetParamTypeSceneMode;
        pSetInputList->pAWBSetParams[AWBSetParamTypeSceneMode].pAWBSetParam =
            static_cast<const VOID*>(&m_setInputs.sceneMode);
        pSetInputList->pAWBSetParams[AWBSetParamTypeSceneMode].sizeOfInputParam = sizeof(UINT32);
    }
    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::RetrieveAWBLockInfo
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::RetrieveAWBLockInfo(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoSetParamList*           pSetInputList)
{
    CAMX_UNREFERENCED_PARAM(pStatsProcessRequestDataInfo);

    CamxResult          result                  = CamxResultSuccess;
    static const UINT   GetProps[]              = { InputControlAWBLock };
    static const UINT   GerPropsLength          = CAMX_ARRAY_SIZE(GetProps);
    VOID*               pData[GerPropsLength]   = { 0 };
    UINT64              offsets[GerPropsLength] = { 0 };

    m_pNode->GetDataList(GetProps, pData, offsets, GerPropsLength);

    if (NULL == pData[0])
    {
        CAMX_LOG_VERBOSE(CamxLogGroupAWB, "InputControlAWBLock is not published!");
        result = CamxResultEFailed;
    }
    else
    {
        if (ControlAWBLockOn == *reinterpret_cast<ControlAWBLockValues*>(pData[0]))
        {
            m_setInputs.lock = TRUE;
        }
        else
        {
            m_setInputs.lock = FALSE;
        }

        pSetInputList->pAWBSetParams[AWBSetParamTypeLock].setParamType     = AWBSetParamTypeLock;
        pSetInputList->pAWBSetParams[AWBSetParamTypeLock].pAWBSetParam     = static_cast<const VOID*>(&m_setInputs.lock);
        pSetInputList->pAWBSetParams[AWBSetParamTypeLock].sizeOfInputParam = sizeof(BOOL);
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::RetrieveROIInfo
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::RetrieveROIInfo(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoSetParamList*           pSetInputList)
{
    CAMX_UNREFERENCED_PARAM(pStatsProcessRequestDataInfo);
    UINT32     metaTagFDROI = 0;
    CamxResult result       = CamxResultSuccess;

    if (TRUE == m_pNode->GetStaticSettings()->useFDUseCasePool)
    {
        metaTagFDROI = PropertyIDUsecaseFDResults;
    }
    else
    {
        result = VendorTagManager::QueryVendorTagLocation(VendorTagSectionOEMFDResults,
            VendorTagNameOEMFDResults,
            &metaTagFDROI);
    }
    static const UINT       GetProps[]              = { metaTagFDROI, InputControlAWBRegions };
    static const UINT       GerPropsLength          = CAMX_ARRAY_SIZE(GetProps);
    VOID*                   pData[GerPropsLength]   = { 0 };
    UINT64                  offsets[GerPropsLength] = { m_pNode->GetStaticSettings()->maxPipelineDelay, 0 };

    if (CamxResultSuccess == result)
    {
        m_pNode->GetDataList(GetProps, pData, offsets, GerPropsLength);
    }

    if (NULL != pData[0])
    {
        CAMX_LOG_VERBOSE(CamxLogGroupAWB, "FD results published");
        FaceROIInformation*    pFaceROIInfo = reinterpret_cast<FaceROIInformation*>(pData[0]);
        for (UINT32 index = 0; index < pFaceROIInfo->ROICount; index++)
        {
            m_setInputs.statsFaceInfo.face[index].roi.left   = pFaceROIInfo->stabilizedROI[index].faceRect.left;
            m_setInputs.statsFaceInfo.face[index].roi.top    = pFaceROIInfo->stabilizedROI[index].faceRect.top;
            m_setInputs.statsFaceInfo.face[index].roi.width  = pFaceROIInfo->stabilizedROI[index].faceRect.width;
            m_setInputs.statsFaceInfo.face[index].roi.height = pFaceROIInfo->stabilizedROI[index].faceRect.height;

            CAMX_LOG_VERBOSE(CamxLogGroupAWB,
                             "Face ROI[%d]: (left: %d, top: %d, width: %d, height: %d)",
                             index,
                             pFaceROIInfo->stabilizedROI[index].faceRect.left,
                             pFaceROIInfo->stabilizedROI[index].faceRect.top,
                             pFaceROIInfo->stabilizedROI[index].faceRect.width,
                             pFaceROIInfo->stabilizedROI[index].faceRect.height);
        }
        m_setInputs.statsFaceInfo.faceCount = pFaceROIInfo->ROICount;
        m_setInputs.statsFaceInfo.requestID = static_cast<UINT32>(pStatsProcessRequestDataInfo->requestId);

        pSetInputList->pAWBSetParams[AWBSetParamTypeFaceROI].setParamType     = AWBSetParamTypeFaceROI;
        pSetInputList->pAWBSetParams[AWBSetParamTypeFaceROI].pAWBSetParam     = &m_setInputs.statsFaceInfo;
        pSetInputList->pAWBSetParams[AWBSetParamTypeFaceROI].sizeOfInputParam = sizeof(StatsFaceInformation);
    }
    else
    {
        CAMX_LOG_VERBOSE(CamxLogGroupAWB, "FD results not published");
    }

    if (NULL != pData[1])
    {
        StatsWeightedROI* pTouchROI = reinterpret_cast<StatsWeightedROI*>(pData[1]);

        m_setInputs.statsTouchROI.ROI.left = pTouchROI->ROI.left;
        m_setInputs.statsTouchROI.ROI.top    = pTouchROI->ROI.top;
        m_setInputs.statsTouchROI.ROI.width  = pTouchROI->ROI.width;
        m_setInputs.statsTouchROI.ROI.height = pTouchROI->ROI.height;
        m_setInputs.statsTouchROI.ROIWeight = pTouchROI->ROIWeight;

        pSetInputList->pAWBSetParams[AWBSetParamTypeTouchROI].setParamType     = AWBSetParamTypeTouchROI;
        pSetInputList->pAWBSetParams[AWBSetParamTypeTouchROI].pAWBSetParam     = &m_setInputs.statsTouchROI;
        pSetInputList->pAWBSetParams[AWBSetParamTypeTouchROI].sizeOfInputParam = sizeof(StatsRectangle);

        CAMX_LOG_VERBOSE(CamxLogGroupAWB,
                         "Touch ROI / ControlAWBRegions : (left: %d, top: %d, width: %d, height: %d)",
                         pTouchROI->ROI.left,
                         pTouchROI->ROI.top,
                         pTouchROI->ROI.width,
                         pTouchROI->ROI.height);

    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::RetrieveFlashInfo
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::RetrieveFlashInfo(
    const StatsProcessRequestData*  pStatsProcessRequestDataInfo,
    AWBAlgoSetParamList*            pSetInputList)
{
    CAMX_UNREFERENCED_PARAM(pStatsProcessRequestDataInfo);

    CamxResult              result                  = CamxResultSuccess;
    static const UINT       GetProps[]              =
    {
        PropertyIDAECInternal,
        PropertyIDAECFrameInfo,
        PropertyIDAECFrameControl,
        InputControlCaptureIntent
    };
    static const UINT       GerPropsLength          = CAMX_ARRAY_SIZE(GetProps);
    VOID*                   pData[GerPropsLength]   = { 0 };
    UINT64                  offsets[GerPropsLength] = { 0 };

    m_pNode->GetDataList(GetProps, pData, offsets, GerPropsLength);

    if ((NULL == pData[0]) || (NULL == pData[1]) || (NULL == pData[2]))
    {
        CAMX_LOG_ERROR(CamxLogGroupAWB,
                       "PropertyIDAECInternal:%p PropertyIDAECFrameInfo:%p PropertyIDAECFrameControl:%p not published",
                       pData[0],
                       pData[1],
                       pData[2]);
        result = CamxResultEFailed;
    }
    else
    {
        AECOutputInternal*          pAECInternalProperty    = reinterpret_cast<AECOutputInternal*>(pData[0]);
        AECFrameInformation*        pAECFrameInfo           = reinterpret_cast<AECFrameInformation*>(pData[1]);
        AECFrameControl*            pAECFrameControl        = reinterpret_cast<AECFrameControl*>(pData[2]);
        ControlCaptureIntentValues* pCaptureIntent          = reinterpret_cast<ControlCaptureIntentValues*>(pData[3]);

        // Only LED type flash for now
        m_setInputs.flashType = AWBAlgoFlashTypeLED;

        pSetInputList->pAWBSetParams[AWBSetParamTypeFlashType].setParamType     = AWBSetParamTypeFlashType;
        pSetInputList->pAWBSetParams[AWBSetParamTypeFlashType].pAWBSetParam     =
            static_cast<const VOID*>(&m_setInputs.flashType);
        pSetInputList->pAWBSetParams[AWBSetParamTypeFlashType].sizeOfInputParam = sizeof(AWBAlgoFlashType);

        m_setInputs.flashInfo.LEDInfluenceRatio = pAECInternalProperty->LEDInfluenceRatio;
        m_setInputs.flashInfo.LEDBGRatio        = pAECInternalProperty->LEDBGRatio;
        m_setInputs.flashInfo.LEDRGRatio        = pAECInternalProperty->LEDRGRatio;

        switch (pAECFrameInfo->AECPreFlashState)
        {
            case PreFlashStateInactive:
                m_setInputs.flashInfo.flashState = AWBAlgoFlashInactive;
                break;
            case PreFlashStateStart:
                m_setInputs.flashInfo.flashState = AWBAlgoPreFlashStart;
                break;
            case PreFlashStateTriggerFD:
                m_setInputs.flashInfo.flashState = AWBAlgoPreFlashTriggerFD;
                break;
            case PreFlashStateTriggerAF:
                m_setInputs.flashInfo.flashState = AWBAlgoPreFlashTriggerAF;
                break;
            case PreFlashStateTriggerAWB:
                m_setInputs.flashInfo.flashState = AWBAlgoPreFlashTriggerAWB;
                break;
            case PreFlashStateCompleteLED:
                m_setInputs.flashInfo.flashState = AWBAlgoPreFlashCompleteLED;
                break;
            case PreFlashStateCompleteNoLED:
                m_setInputs.flashInfo.flashState = AWBAlgoPreFlashCompleteNoLED;
                break;
            default:
                m_setInputs.flashInfo.flashState = AWBAlgoFlashInactive;
                break;
        }

        if ((ControlCaptureIntentStillCapture == *pCaptureIntent)                  &&
            ((pAECFrameControl->LEDCurrents[LEDSetting1] > 0) || (pAECFrameControl->LEDCurrents[LEDSetting2] > 0)))
        {
            m_setInputs.flashInfo.flashState = AWBAlgoMainFlash;
        }

        switch (pAECFrameControl->flashInfo)
        {
            case FlashInfoTypeOff:
                m_setInputs.flashInfo.flashType = AWBAlgoFlashOff;
                break;
            case FlashInfoTypePre:
                m_setInputs.flashInfo.flashType = AWBAlgoFlashPre;
                break;
            case FlashInfoTypeMain:
                m_setInputs.flashInfo.flashType = AWBAlgoFlashMain;
                break;
            case FlashInfoTypeMax:
                m_setInputs.flashInfo.flashType = AWBAlgoFlashMax;
                break;
            default:
                CAMX_ASSERT_ALWAYS_MESSAGE("Invalid Flash info type");
                break;
        }

        pSetInputList->pAWBSetParams[AWBSetParamTypeFlashData].setParamType = AWBSetParamTypeFlashData;
        pSetInputList->pAWBSetParams[AWBSetParamTypeFlashData].pAWBSetParam =
            static_cast<const VOID*>(&m_setInputs.flashInfo);
        pSetInputList->pAWBSetParams[AWBSetParamTypeFlashData].sizeOfInputParam = sizeof(AWBAlgoFlashInformation);
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::SetPeerInfo
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::SetPeerInfo(
    const StatsProcessRequestData*  pStatsProcessRequestDataInfo,
    AWBAlgoSetParamList*            pSetInputList,
    UINT                            peerPipelineId)
{
    CamxResult  result          = CamxResultEFailed;
    UINT64      requestID       = pStatsProcessRequestDataInfo->requestId;
    UINT64      peerRequestID   = pStatsProcessRequestDataInfo->pMultiRequestSync->requestID[peerPipelineId];
    INT64       requestDelta    = 0;

    if (TRUE == pStatsProcessRequestDataInfo->pMultiRequestSync->isMultiRequest)
    {
        if (StatsAlgoProcessMapping == pStatsProcessRequestDataInfo->algoAction)
        {
            // Slave/Follower
            requestDelta = requestID - peerRequestID;
        }
        else if (StatsAlgoProcessRequest == pStatsProcessRequestDataInfo->algoAction)
        {
            // Master, will depend on previous slave
            requestDelta = requestID - peerRequestID + 1;
        }
    }

    // Get property from peer pipeline
    const UINT  getProps[]  = { PropertyIDAWBPeerInfo };
    VOID*       pData[1]    = { 0 };
    UINT64      offsets[1]  = { static_cast<UINT64>(abs(requestDelta)) };
    BOOL        negates[1]  = { (requestDelta < 0) ? TRUE : FALSE };

    result = m_pNode->GetDataListFromPipeline(getProps, pData, offsets, 1, negates, peerPipelineId);
    if (NULL == pData[0])
    {
        CAMX_LOG_VERBOSE(CamxLogGroupAWB, "PropertyIDAWBPeerInfo not published, Req:%llu requestDelta:%lld",
                         requestID, requestDelta);
    }
    else
    {
        m_setInputs.pPeerInfo = *(static_cast<VOID**>(pData[0]));
        CAMX_LOG_VERBOSE(CamxLogGroupAWB, "Peer info: %p, Req:%llu requestDelta:%lld",
                         m_setInputs.pPeerInfo, requestID, requestDelta);

        pSetInputList->pAWBSetParams[AWBSetParamTypePeerInfo].setParamType     = AWBSetParamTypePeerInfo;
        pSetInputList->pAWBSetParams[AWBSetParamTypePeerInfo].pAWBSetParam     = m_setInputs.pPeerInfo;
        pSetInputList->pAWBSetParams[AWBSetParamTypePeerInfo].sizeOfInputParam = sizeof(VOID*);
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::GetAlgoProcessInput
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::GetAlgoProcessInput(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoInputList*              pInputList,
    BOOL                           processStats)
{
    CAMX_ENTRYEXIT(CamxLogGroupAWB);

    CamxResult result       = CamxResultSuccess;
    pInputList->pAWBInputs  = m_processInputArray;
    pInputList->inputCount  = AWBInputTypeLastIndex - 1;

    result = GetRequestNumber(pStatsProcessRequestDataInfo, pInputList);

    if (CamxResultSuccess == result)
    {
        result = GetStatistics(pStatsProcessRequestDataInfo, pInputList, processStats);
    }

    if (CamxResultSuccess == result)
    {
        result = GetAECData(pInputList);
    }

    if (CamxResultSuccess == result)
    {
        result = GetVendorTags(pInputList);
    }

    if (CamxResultSuccess == result)
    {
        result = GetDebugDataBuffer(pStatsProcessRequestDataInfo, pInputList);
    }

    if (CamxResultSuccess == result)
    {
        result = GetChiStatsSession(pStatsProcessRequestDataInfo, pInputList);
    }

    if (CamxResultSuccess == result)
    {
        result = SetCameraInformation(pStatsProcessRequestDataInfo, pInputList, processStats);
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::GetAlgoExpectedOutputList
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID CAWBIOUtil::GetAlgoExpectedOutputList(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoOutputList*             pOutputList)
{
    CAMX_ENTRYEXIT(CamxLogGroupAWB);

    CAMX_UNREFERENCED_PARAM(pStatsProcessRequestDataInfo);

    pOutputList->pAWBOutputs = m_processOutputArray;
    pOutputList->outputCount = AWBOutputTypeLastIndex;

    /// @todo (CAMX-1233): Once debug data is defined, add it here.
    // pOutputList->pAWBOutputs[AWBOutputTypeDebugData].outputType          = AWBOutputTypeDebugData;
    // pOutputList->pAWBOutputs[AWBOutputTypeDebugData].pAWBOutput          = &m_outputs.debugData;
    // pOutputList->pAWBOutputs[AWBOutputTypeDebugData].sizeOfAWBOutput     = sizeof(m_outputs.debugData);

    pOutputList->pAWBOutputs[AWBOutputTypeGains].outputType                 = AWBOutputTypeGains;
    pOutputList->pAWBOutputs[AWBOutputTypeGains].pAWBOutput                 = &m_outputs.gains;
    pOutputList->pAWBOutputs[AWBOutputTypeGains].sizeOfAWBOutput            = sizeof(m_outputs.gains);

    pOutputList->pAWBOutputs[AWBOutputTypeColorTemperature].outputType      = AWBOutputTypeColorTemperature;
    pOutputList->pAWBOutputs[AWBOutputTypeColorTemperature].pAWBOutput      = &m_outputs.cct;
    pOutputList->pAWBOutputs[AWBOutputTypeColorTemperature].sizeOfAWBOutput = sizeof(m_outputs.cct);

    pOutputList->pAWBOutputs[AWBOutputTypeIlluminantType].outputType        = AWBOutputTypeIlluminantType;
    pOutputList->pAWBOutputs[AWBOutputTypeIlluminantType].pAWBOutput        = &m_outputs.illuminantType;
    pOutputList->pAWBOutputs[AWBOutputTypeIlluminantType].sizeOfAWBOutput   = sizeof(m_outputs.illuminantType);

    pOutputList->pAWBOutputs[AWBOutputTypeSampleDecision].outputType        = AWBOutputTypeSampleDecision;
    pOutputList->pAWBOutputs[AWBOutputTypeSampleDecision].pAWBOutput        = m_outputs.sampleDecision;
    pOutputList->pAWBOutputs[AWBOutputTypeSampleDecision].sizeOfAWBOutput   = sizeof(m_outputs.sampleDecision);

    pOutputList->pAWBOutputs[AWBOutputTypeBGConfig].outputType              = AWBOutputTypeBGConfig;
    pOutputList->pAWBOutputs[AWBOutputTypeBGConfig].pAWBOutput              = &m_outputs.BGConfig;
    pOutputList->pAWBOutputs[AWBOutputTypeBGConfig].sizeOfAWBOutput         = sizeof(m_outputs.BGConfig);

    pOutputList->pAWBOutputs[AWBOutputTypeState].outputType                 = AWBOutputTypeState;
    pOutputList->pAWBOutputs[AWBOutputTypeState].pAWBOutput                 = &m_outputs.state;
    pOutputList->pAWBOutputs[AWBOutputTypeState].sizeOfAWBOutput            = sizeof(m_outputs.state);

    pOutputList->pAWBOutputs[AWBOutputTypeMode].outputType                  = AWBOutputTypeMode;
    pOutputList->pAWBOutputs[AWBOutputTypeMode].pAWBOutput                  = &m_outputs.mode;
    pOutputList->pAWBOutputs[AWBOutputTypeMode].sizeOfAWBOutput             = sizeof(m_outputs.mode);

    pOutputList->pAWBOutputs[AWBOutputTypeLock].outputType                  = AWBOutputTypeLock;
    pOutputList->pAWBOutputs[AWBOutputTypeLock].pAWBOutput                  = &m_outputs.lock;
    pOutputList->pAWBOutputs[AWBOutputTypeLock].sizeOfAWBOutput             = sizeof(m_outputs.lock);

    pOutputList->pAWBOutputs[AWBOutputTypeVendorTag].outputType             = AWBOutputTypeVendorTag;
    pOutputList->pAWBOutputs[AWBOutputTypeVendorTag].pAWBOutput             = &m_outputs.vendorTagList;
    pOutputList->pAWBOutputs[AWBOutputTypeVendorTag].sizeOfAWBOutput        = sizeof(m_outputs.vendorTagList);

    pOutputList->pAWBOutputs[AWBOutputTypeCCM].outputType                   = AWBOutputTypeCCM;
    pOutputList->pAWBOutputs[AWBOutputTypeCCM].pAWBOutput                   = &m_outputs.CCMList;
    pOutputList->pAWBOutputs[AWBOutputTypeCCM].sizeOfAWBOutput              = sizeof(StatsAWBCCMList);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::GetAlgoGetParamInputOutput
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::GetAlgoGetParamInputOutput(
    const StatsProcessRequestData*  pStatsProcessRequestDataInfo,
    AWBAlgoGetParam*                pGetParam)
{
    CAMX_ENTRYEXIT(CamxLogGroupAWB);

    CamxResult result                             = CamxResultSuccess;
    pGetParam->inputInfoList.pGetParamInputs      = m_getParamInputArray;
    pGetParam->inputInfoList.getParamInputCount   = AWBGetParamInputTypeLastIndex;

    pGetParam->outputInfoList.pGetParamOutputs    = m_getParamOutputArray;
    pGetParam->outputInfoList.getParamOutputCount = AWBGetParamOutputTypeLastIndex;

    // invalidate input/output list

    for (UINT32 i = 0; i < AWBGetParamInputTypeLastIndex; i++)
    {
        m_getParamInputArray[i].getParamInputType = AWBGetParamInputTypeInvalid;
    }
    for (UINT32 i = 0; i < AWBGetParamOutputTypeLastIndex; i++)
    {
        m_getParamOutputArray[i].getParamOutputType = AWBGetParamOutputTypeInvalid;
    }

    // Set camera information for get
    m_getParamInputArray[AWBGetParamInputTypeCameraInfo].getParamInputType   = AWBGetParamInputTypeCameraInfo;
    m_getParamInputArray[AWBGetParamInputTypeCameraInfo].pGetParamInput      = reinterpret_cast<VOID*>(&m_inputs.cameraInfo);
    m_getParamInputArray[AWBGetParamInputTypeCameraInfo].sizeOfGetParamInput = sizeof(StatsCameraInfo);

    if (AWBGetParamTypeLastOutput == pGetParam->type)
    {
        GetAlgoExpectedOutputList(pStatsProcessRequestDataInfo, &m_outputs.lastOutputList);

        m_getParamOutputArray[AWBGetParamOutputTypeOutputList].getParamOutputType          = AWBGetParamOutputTypeOutputList;
        m_getParamOutputArray[AWBGetParamOutputTypeOutputList].pGetParamOutput             = &m_outputs.lastOutputList;
        m_getParamOutputArray[AWBGetParamOutputTypeOutputList].sizeOfGetParamOutput        = sizeof(m_outputs.lastOutputList);
        m_getParamOutputArray[AWBGetParamOutputTypeOutputList].sizeOfWrittenGetParamOutput = 0;
    }
    else if (AWBGetParamTypeFlashEstimationState == pGetParam->type)
    {
        m_getParamOutputArray[AWBGetParamOutputTypeFlashEstimationProgress].getParamOutputType          =
            AWBGetParamOutputTypeFlashEstimationProgress;
        m_getParamOutputArray[AWBGetParamOutputTypeFlashEstimationProgress].pGetParamOutput             =
            &m_algoFlashEstimationState;
        m_getParamOutputArray[AWBGetParamOutputTypeFlashEstimationProgress].sizeOfGetParamOutput        =
            sizeof(m_algoFlashEstimationState);
        m_getParamOutputArray[AWBGetParamOutputTypeFlashEstimationProgress].sizeOfWrittenGetParamOutput = 0;
    }
    else if (AWBGetParamTypeDependentVendorTags == pGetParam->type)
    {
        Utils::Memset(&m_vendorTagInputList, 0, sizeof(m_vendorTagInputList));

        m_getParamOutputArray[AWBGetParamOutputTypeDependentVendorTags].getParamOutputType          =
            AWBGetParamOutputTypeDependentVendorTags;
        m_getParamOutputArray[AWBGetParamOutputTypeDependentVendorTags].pGetParamOutput             = &m_vendorTagInputList;
        m_getParamOutputArray[AWBGetParamOutputTypeDependentVendorTags].sizeOfGetParamOutput        =
            sizeof(m_vendorTagInputList);
        m_getParamOutputArray[AWBGetParamOutputTypeDependentVendorTags].sizeOfWrittenGetParamOutput = 0;
    }
    else if (AWBGetParamTypePublishingVendorTagsInfo == pGetParam->type)
    {
        Utils::Memset(&m_vendorTagInputList, 0, sizeof(m_vendorTagInputList));

        m_getParamOutputArray[AWBGetParamOutputTypePublishingVendorTagsInfo].getParamOutputType          =
            AWBGetParamOutputTypePublishingVendorTagsInfo;
        m_getParamOutputArray[AWBGetParamOutputTypePublishingVendorTagsInfo].pGetParamOutput             =
            &m_vendorTagInfoOutputputList;
        m_getParamOutputArray[AWBGetParamOutputTypePublishingVendorTagsInfo].sizeOfGetParamOutput        =
            sizeof(m_vendorTagInfoOutputputList);
        m_getParamOutputArray[AWBGetParamOutputTypePublishingVendorTagsInfo].sizeOfWrittenGetParamOutput = 0;
    }
    else if (AWBGetParamTypeFlashOutput == pGetParam->type)
    {
        for (UINT32 i = 0; i < AWBOutputTypeLastIndex; i++)
        {
            m_processOutputArray[i].outputType = AWBOutputTypeInvalid;
        }
        m_processOutputArray[AWBOutputTypeGains].outputType                                = AWBOutputTypeGains;
        m_processOutputArray[AWBOutputTypeGains].pAWBOutput                                = &m_outputs.flashGains;
        m_processOutputArray[AWBOutputTypeGains].sizeOfAWBOutput                           = sizeof(m_outputs.flashGains);

        m_processOutputArray[AWBOutputTypeColorTemperature].outputType                     = AWBOutputTypeColorTemperature;
        m_processOutputArray[AWBOutputTypeColorTemperature].pAWBOutput                     = &m_outputs.flashCCT;
        m_processOutputArray[AWBOutputTypeColorTemperature].sizeOfAWBOutput                = sizeof(m_outputs.flashCCT);

        m_processOutputArray[AWBOutputTypeCCM].outputType                                  = AWBOutputTypeCCM;
        m_processOutputArray[AWBOutputTypeCCM].pAWBOutput                                  = &m_outputs.flashCCMList;
        m_processOutputArray[AWBOutputTypeCCM].sizeOfAWBOutput                             = sizeof(m_outputs.flashCCMList);

        m_outputs.flashOutputList.pAWBOutputs                                              = m_processOutputArray;
        m_outputs.flashOutputList.outputCount                                              = AWBOutputTypeLastIndex;

        m_getParamOutputArray[AWBGetParamOutputTypeOutputList].getParamOutputType          = AWBGetParamOutputTypeOutputList;
        m_getParamOutputArray[AWBGetParamOutputTypeOutputList].pGetParamOutput             = &m_outputs.flashOutputList;
        m_getParamOutputArray[AWBGetParamOutputTypeOutputList].sizeOfGetParamOutput        = sizeof(m_outputs.flashOutputList);
        m_getParamOutputArray[AWBGetParamOutputTypeOutputList].sizeOfWrittenGetParamOutput = 0;
    }
    else if (AWBGetParamTypePeerInfo == pGetParam->type)
    {
        m_getParamOutputArray[AWBGetParamOutputTypePeerInfo].getParamOutputType          = AWBGetParamOutputTypePeerInfo;
        m_getParamOutputArray[AWBGetParamOutputTypePeerInfo].pGetParamOutput             = &m_outputs.pPeerInfo;
        m_getParamOutputArray[AWBGetParamOutputTypePeerInfo].sizeOfGetParamOutput        = sizeof(VOID*);
        m_getParamOutputArray[AWBGetParamOutputTypePeerInfo].sizeOfWrittenGetParamOutput = 0;
    }
    else if (AWBGetParamTypeBGConfig == pGetParam->type)
    {
        m_getParamOutputArray[AWBGetParamOutputTypeBGConfig].getParamOutputType          = AWBGetParamOutputTypeBGConfig;
        m_getParamOutputArray[AWBGetParamOutputTypeBGConfig].pGetParamOutput             = &m_outputs.BGConfig;
        m_getParamOutputArray[AWBGetParamOutputTypeBGConfig].sizeOfGetParamOutput        = sizeof(m_outputs.BGConfig);
        m_getParamOutputArray[AWBGetParamOutputTypeBGConfig].sizeOfWrittenGetParamOutput = 0;
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::GetAlgoSetParamInput
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::GetAlgoSetParamInput(
    const StatsProcessRequestData* pStatsProcessRequestDataInfo,
    AWBAlgoSetParamList*           pInputList)
{
    CAMX_UNREFERENCED_PARAM(pStatsProcessRequestDataInfo);

    CamxResult result = CamxResultSuccess;

    pInputList->pAWBSetParams       = m_setParamInputArray;
    pInputList->inputParamsCount    = AWBSetParamTypeLastIndex;

    // AWB set debug data mode
    m_setInputs.debugDataMode = 0; // Hardcode now as debug data mode is not defined yet
    pInputList->pAWBSetParams[AWBSetParamTypeDebugDataMode].setParamType     = AWBSetParamTypeInvalid;
    pInputList->pAWBSetParams[AWBSetParamTypeDebugDataMode].pAWBSetParam     =
        static_cast<const VOID*>(&m_setInputs.debugDataMode);
    pInputList->pAWBSetParams[AWBSetParamTypeDebugDataMode].sizeOfInputParam = sizeof(INT32);

    // AWB set Chromatix data
    m_setInputs.statsTuningData.pTuningSetManager    = static_cast<VOID*>(m_pTuningManager->GetChromatix());
    m_setInputs.statsTuningData.pTuningModeSelectors =
        reinterpret_cast<TuningMode*>(&pStatsProcessRequestDataInfo->pTuningModeData->TuningMode[0]);
    m_setInputs.statsTuningData.numSelectors =
        pStatsProcessRequestDataInfo->pTuningModeData->noOfSelectionParameter;
    CAMX_LOG_VERBOSE(CamxLogGroupAWB,
        "Tuning data as mode: %d usecase %d  feature1 %d feature2 %d scene %d, effect %d,",
        pStatsProcessRequestDataInfo->pTuningModeData->TuningMode[0].mode,
        pStatsProcessRequestDataInfo->pTuningModeData->TuningMode[2].subMode.usecase,
        pStatsProcessRequestDataInfo->pTuningModeData->TuningMode[3].subMode.feature1,
        pStatsProcessRequestDataInfo->pTuningModeData->TuningMode[4].subMode.feature2,
        pStatsProcessRequestDataInfo->pTuningModeData->TuningMode[5].subMode.scene,
        pStatsProcessRequestDataInfo->pTuningModeData->TuningMode[6].subMode.effect);

    pInputList->pAWBSetParams[AWBSetParamTypeChromatixData].setParamType     = AWBSetParamTypeChromatixData;
    pInputList->pAWBSetParams[AWBSetParamTypeChromatixData].pAWBSetParam     =
        static_cast<const VOID*>(&m_setInputs.statsTuningData);
    pInputList->pAWBSetParams[AWBSetParamTypeChromatixData].sizeOfInputParam = sizeof(StatsTuningData);

    // AWB set camera infomation
    pInputList->pAWBSetParams[AWBSetParamTypeCameraInfo].setParamType     = AWBSetParamTypeCameraInfo;
    pInputList->pAWBSetParams[AWBSetParamTypeCameraInfo].pAWBSetParam     =
        static_cast<const VOID*>(&m_inputs.cameraInfo);
    pInputList->pAWBSetParams[AWBSetParamTypeCameraInfo].sizeOfInputParam = sizeof(StatsCameraInfo);

    // AWB set sensor info
    RetrieveSensorInfo(pStatsProcessRequestDataInfo, pInputList);

    // AWB set stats window info
    RetrieveStatsWindowInfo(pStatsProcessRequestDataInfo, pInputList);

    // AWB set calibration data
    RetrieveCalibrationData(pStatsProcessRequestDataInfo, pInputList);

    // AWB set white balance mode
    RetrieveAWBMode(pStatsProcessRequestDataInfo, pInputList);

    if (AWBAlgoModeOff == m_setInputs.algoMode)
    {
        // AWB set manual white balance info
        RetrieveManualWhiteBalanceInfo(pStatsProcessRequestDataInfo, pInputList);
    }

    // AWB set lock
    RetrieveAWBLockInfo(pStatsProcessRequestDataInfo, pInputList);

    // AWB set scene mode
    RetrieveSceneMode(pStatsProcessRequestDataInfo, pInputList);

    // AWB set face and touch ROI
    RetrieveROIInfo(pStatsProcessRequestDataInfo, pInputList);

    // AWB set flash type and data
    RetrieveFlashInfo(pStatsProcessRequestDataInfo, pInputList);

    CAMX_LOG_VERBOSE(CamxLogGroupAWB, "AWB Input: Mode:%d Lock:%d SceneMode:%d faceCnt:%d, "
                     "FlashState:%d FlashInfoType:%d LED: InfluenceRatio:%f R/G_Ratio:%f B/G_Ratio:%f ",
                     m_setInputs.algoMode,
                     m_setInputs.lock,
                     m_setInputs.sceneMode,
                     m_setInputs.statsFaceInfo.faceCount,
                     m_setInputs.flashInfo.flashState,
                     m_setInputs.flashInfo.flashType,
                     m_setInputs.flashInfo.LEDInfluenceRatio,
                     m_setInputs.flashInfo.LEDRGRatio,
                     m_setInputs.flashInfo.LEDBGRatio);

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::GetFrameAndStatControl
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID CAWBIOUtil::GetFrameAndStatControl(
    AWBFrameControl*   pFrameControl,
    AWBStatsControl*   pStatsControl)
{
    // Set control gains
    pFrameControl->AWBGains.rGain = m_outputs.gains.red;
    pFrameControl->AWBGains.gGain = m_outputs.gains.green;
    pFrameControl->AWBGains.bGain = m_outputs.gains.blue;

    // Set Color temperature
    pFrameControl->colorTemperature = m_outputs.cct;

    // set CCM values
    pFrameControl->numValidCCMs = m_outputs.CCMList.numValidCCMs;

    for (UINT32 ccmIndex = 0; ccmIndex < pFrameControl->numValidCCMs; ccmIndex++)
    {
        pFrameControl->AWBCCM[ccmIndex].isCCMOverrideEnabled = m_outputs.CCMList.CCM[ccmIndex].isCCMOverrideEnabled;

        if (TRUE == pFrameControl->AWBCCM[ccmIndex].isCCMOverrideEnabled)
        {
            for (UINT i = 0; i < AWBNumCCMRows; i++)
            {
                for (UINT j = 0; j < AWBNumCCMCols; j++)
                {
                    pFrameControl->AWBCCM[ccmIndex].CCM[i][j] = m_outputs.CCMList.CCM[ccmIndex].CCM[i][j];
                }

                pFrameControl->AWBCCM[ccmIndex].CCMOffset[i] = m_outputs.CCMList.CCM[ccmIndex].CCMOffset[i];
            }
        }
    }

    // Set stats configuration
    FillBGConfigurationData(&pStatsControl->statsConfig, &m_outputs.BGConfig);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::IsAECSettled
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CAWBIOUtil::IsAECSettled()
{
    BOOL aecSettled = FALSE;
    static const UINT   GetProps[]              = { PropertyIDAECFrameInfo };
    static const UINT   GetPropsLength          = CAMX_ARRAY_SIZE(GetProps);
    VOID*               pData[GetPropsLength]   = { 0 };
    UINT64              offsets[GetPropsLength] = { 0 };

    m_pNode->GetDataList(GetProps, pData, offsets, GetPropsLength);

    if (NULL == pData[0])
    {
        CAMX_LOG_ERROR(CamxLogGroupAWB, "PropertyIDAECFrameInfo is not published!");
    }
    else
    {
        aecSettled = reinterpret_cast<AECFrameInformation*>(pData[0])->AECSettled;
    }

    return aecSettled;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::GetFlashFrameControl
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID CAWBIOUtil::GetFlashFrameControl(
    AWBFrameControl*   pFlashFrameControl)
{
    if ((m_outputs.flashGains.red <= 0.0f) || (m_outputs.flashGains.green <= 0.0f) || (m_outputs.flashGains.blue <= 0.0f))
    {
        m_outputs.flashGains = m_outputs.gains;
        m_outputs.flashCCT   = m_outputs.cct;

        CAMX_LOG_WARN(CamxLogGroupAWB, "Invalid Algo Main Flash gain. Using preflash gain as main flash gain.");
    }

    // Set flash control gains
    pFlashFrameControl->AWBGains.rGain = m_outputs.flashGains.red;
    pFlashFrameControl->AWBGains.gGain = m_outputs.flashGains.green;
    pFlashFrameControl->AWBGains.bGain = m_outputs.flashGains.blue;

    // Set flash Color temperature
    pFlashFrameControl->colorTemperature = m_outputs.flashCCT;

    // set CCM values
    pFlashFrameControl->numValidCCMs = m_outputs.flashCCMList.numValidCCMs;

    for (UINT32 ccmIndex = 0; ccmIndex < pFlashFrameControl->numValidCCMs; ccmIndex++)
    {
        pFlashFrameControl->AWBCCM[ccmIndex].isCCMOverrideEnabled = m_outputs.flashCCMList.CCM[ccmIndex].isCCMOverrideEnabled;

        if (TRUE == pFlashFrameControl->AWBCCM[ccmIndex].isCCMOverrideEnabled)
        {
            for (UINT i = 0; i < AWBNumCCMRows; i++)
            {
                for (UINT j = 0; j < AWBNumCCMCols; j++)
                {
                    pFlashFrameControl->AWBCCM[ccmIndex].CCM[i][j] = m_outputs.flashCCMList.CCM[ccmIndex].CCM[i][j];
                }

                pFlashFrameControl->AWBCCM[ccmIndex].CCMOffset[i] = m_outputs.flashCCMList.CCM[ccmIndex].CCMOffset[i];
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::PrePublishMetadata
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID CAWBIOUtil::PrePublishMetadata()
{
    AWBFrameControl frameControl = {{0}};
    AWBStatsControl statsControl = {{{0}}};

    GetFrameAndStatControl(&frameControl, &statsControl);

    static const UINT WriteProps[] =
    {
        PropertyIDUsecaseAWBFrameControl,
        PropertyIDUsecaseAWBStatsControl
    };
    const VOID* pOutputData[CAMX_ARRAY_SIZE(WriteProps)] =
    {
        &frameControl,
        &statsControl
    };
    UINT pDataCount[CAMX_ARRAY_SIZE(WriteProps)]  =
    {
        sizeof(frameControl),
        sizeof(statsControl)
    };

    // Writing only usecase, so can write outside EPR
    m_pNode->WriteDataList(WriteProps, pOutputData, pDataCount, CAMX_ARRAY_SIZE(WriteProps));
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::PublishSkippedFrameOutput
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::PublishSkippedFrameOutput() const
{
    CamxResult result                                       = CamxResultSuccess;
    static const UINT AWBPropertyList[]                     =
    {
        PropertyIDAWBFrameControl,
        PropertyIDAWBFrameInfo,
        PropertyIDAWBInternal,
        PropertyIDAWBStatsControl
    };
    static const UINT AWBPropertyListLength                 = CAMX_ARRAY_SIZE(AWBPropertyList);
    VOID* pData[AWBPropertyListLength]                      = { NULL };
    UINT64 AWBPropertyListDataOffset[AWBPropertyListLength] = { 1, 1, 1, 1 }; // Read from previous request id

    m_pNode->GetDataList(AWBPropertyList, pData, AWBPropertyListDataOffset, AWBPropertyListLength);

    if ((NULL == pData[0]) || (NULL == pData[1]) || (NULL == pData[2]) || (NULL == pData[3]))
    {
        CAMX_LOG_ERROR(CamxLogGroupAWB,
                       "PropertyIDAWBFrameControl(0x%x) PropertyIDAWBFrameInfo(0x%x) "
                       "PropertyIDAWBInternal(0x%x) PropertyIDAWBStatsControl(0x%x) is not published",
                       pData[0],
                       pData[1],
                       pData[2],
                       pData[3]);
        result = CamxResultEInvalidState;
    }
    else
    {
        const VOID* pOutputData[AWBPropertyListLength]  = { pData[0], pData[1], pData[2], pData[3] };
        UINT pDataSize[AWBPropertyListLength]           =
        {
            sizeof(AWBFrameControl),
            sizeof(AWBFrameInfo),
            sizeof(AWBOutputInternal),
            sizeof(AWBStatsControl)
        };

        result = m_pNode->WriteDataList(AWBPropertyList, pOutputData, pDataSize, AWBPropertyListLength);
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::PublishMetadata
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::PublishMetadata(
    const StatsProcessRequestData*  pStatsProcessRequestDataInfo,
    AWBAlgoOutputList*              pProcessOutput,
    AWBAlgoGetParamOutputList*      pGetParamOutput)
{
    CamxResult result = CamxResultSuccess;

    CAMX_ASSERT((NULL != pStatsProcessRequestDataInfo) && ((NULL != pProcessOutput) || (NULL != pGetParamOutput)));

    result = PublishFrameControlToMainMetadata();

    if (CamxResultSuccess == result)
    {
        result = PublishFrameInformationToMainMetadata();
    }

    if (CamxResultSuccess == result)
    {
        if (TRUE == pStatsProcessRequestDataInfo->reportConverged)
        {
            m_outputs.state = AWBAlgoStateConverged;
        }
        result = PublishExternalCameraMetadata(pProcessOutput, pGetParamOutput);
    }

    if (CamxResultSuccess == result)
    {
        result = PublishToInternalMetadata();
    }

    if (CamxResultSuccess == result)
    {
        result = PublishPropertyDebugData();
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::PublishExternalCameraMetadata
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::PublishExternalCameraMetadata(
    AWBAlgoOutputList*              pProcessOutput,
    AWBAlgoGetParamOutputList*      pGetParamOutput)
{
    BYTE              lockState                                = static_cast<BYTE>(m_outputs.lock);
    UINT8             mode                                     = static_cast<UINT8>(m_outputs.mode);
    UINT8             state                                    = static_cast<UINT8>(m_outputs.state);
    CamxResult        result                                   = CamxResultSuccess;
    static const UINT WriteProps[]                             = {ControlAWBLock, ControlAWBMode, ControlAWBState };
    const VOID*       pOutputData[CAMX_ARRAY_SIZE(WriteProps)] = { &lockState, &mode, &state };
    UINT              pDataCount[CAMX_ARRAY_SIZE(WriteProps)]  = { 1, 1, 1 };

    result = m_pNode->WriteDataList(WriteProps, pOutputData, pDataCount, CAMX_ARRAY_SIZE(WriteProps));

    if (CamxResultSuccess == result)
    {
        result = PublishVendorTagMetadata(pProcessOutput, pGetParamOutput);
    }
    CAMX_LOG_VERBOSE(CamxLogGroupAWB, "Published AWB Meta: Lock: %d Mode: %d state: %d",
                     lockState, mode, state);

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// CAWBIOUtil::PublishVendorTagMetadata()
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::PublishVendorTagMetadata(
    AWBAlgoOutputList*              pProcessOutput,
    AWBAlgoGetParamOutputList*      pGetParamOutput)
{
    CAMX_UNREFERENCED_PARAM(pGetParamOutput);

    CamxResult      result          = CamxResultSuccess;

    CAMX_ASSERT(NULL != pProcessOutput);
    if (0 != pProcessOutput->pAWBOutputs[AWBOutputTypeVendorTag].sizeOfAWBOutput)
    {
        StatsVendorTagList* pVendorTagOutput =
            static_cast<StatsVendorTagList*>(pProcessOutput->pAWBOutputs[AWBOutputTypeVendorTag].pAWBOutput);
        CAMX_ASSERT_MESSAGE(NULL != pVendorTagOutput, "pVendorTagOutput NULL pointer");

        for (UINT32 i = 0; i < pVendorTagOutput->vendorTagCount; i++)
        {
            if (0 == pVendorTagOutput->vendorTag[i].sizeOfWrittenData)
            {
                continue;
            }

            static const UINT WriteProps[]                             = {pVendorTagOutput->vendorTag[i].vendorTagId};
            const VOID*       pOutputData[CAMX_ARRAY_SIZE(WriteProps)] = { pVendorTagOutput->vendorTag[i].pData };
            UINT              pDataCount[CAMX_ARRAY_SIZE(WriteProps)]  = { 1 };

            result = m_pNode->WriteDataList(WriteProps, pOutputData, pDataCount, CAMX_ARRAY_SIZE(WriteProps));

            CAMX_LOG_VERBOSE(CamxLogGroupAWB,
                             "Published VendorTag(%u) size(%d) pData(%p). Result = %d",
                             pVendorTagOutput->vendorTag[i].vendorTagId,
                             pVendorTagOutput->vendorTag[i].dataSize,
                             pVendorTagOutput->vendorTag[i].pData,
                             result);
        }
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::PublishFrameControlToMainMetadata
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::PublishFrameControlToMainMetadata()
{
    CamxResult      result          = CamxResultSuccess;
    AWBFrameControl frameControl    = {{0}};
    AWBStatsControl statsControl    = {{{0}}};

    GetFrameAndStatControl(&frameControl, &statsControl);
    // Overwrite Frame control with flash gains for flash snapshot
    if ((AWBAlgoMainFlash == m_setInputs.flashInfo.flashState) ||
        (m_numberOfFramesToSkip > 0))
    {
        /* We need to skip "processing of stats" for number of frames after main flash */
        const StaticSettings*   pStaticSettings = HwEnvironment::GetInstance()->GetStaticSettings();
        CAMX_ASSERT(pStaticSettings != NULL);

        if (m_numberOfFramesToSkip == 0)
        {
            m_numberOfFramesToSkip = pStaticSettings->numberOfFramesToSkip;
        }
        else
        {
            m_numberOfFramesToSkip--;
        }
        GetFlashFrameControl(&frameControl);
        CAMX_LOG_INFO(CamxLogGroupAWB,
                      "Main Flash Snapshot is triggered for reqID: %llu. Gain(R:%f, G:%f, B:%f) CCT(%d)",
                      m_inputs.requestNumber,
                      frameControl.AWBGains.rGain,
                      frameControl.AWBGains.gGain,
                      frameControl.AWBGains.bGain,
                      frameControl.colorTemperature);
    }

    UINT32 awbTag = 0;
    result        = VendorTagManager::QueryVendorTagLocation("org.quic.camera2.statsconfigs", "AWBFrameControl", &awbTag);

    static const UINT WriteProps[] = { PropertyIDAWBFrameControl, PropertyIDAWBStatsControl, awbTag };

    const VOID* pOutputData[CAMX_ARRAY_SIZE(WriteProps)] = { &frameControl, &statsControl, &frameControl };

    UINT pDataCount[CAMX_ARRAY_SIZE(WriteProps)]  = { sizeof(frameControl), sizeof(statsControl), sizeof(frameControl) };
    UINT length                                   = CAMX_ARRAY_SIZE(WriteProps);

    // Write and publish the AWB properties
    result = m_pNode->WriteDataList(WriteProps, pOutputData, pDataCount, length);

    CAMX_LOG_VERBOSE(CamxLogGroupAWB,
                     "Published PropertyIDAWBFrameControl for reqID: %llu camId:%d"
                     " Gain(R:%f, G:%f, B:%f) CCT(%d), FlashState: %d",
                     m_inputs.requestNumber,
                     m_inputs.cameraInfo.cameraId,
                     frameControl.AWBGains.rGain,
                     frameControl.AWBGains.gGain,
                     frameControl.AWBGains.bGain,
                     frameControl.colorTemperature,
                     m_setInputs.flashInfo.flashState);

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::PublishFrameInformationToMainMetadata
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::PublishFrameInformationToMainMetadata()
{
    AWBFrameInfo      info                                     = {{0}};
    static const UINT WriteProps[]                             = {PropertyIDAWBFrameInfo};
    const VOID*       pOutputData[CAMX_ARRAY_SIZE(WriteProps)] = { &info };
    UINT              pDataCount[CAMX_ARRAY_SIZE(WriteProps)]  = { sizeof(info) };

    // Set information gains
    info.AWBGains.rGain = m_outputs.gains.red;
    info.AWBGains.gGain = m_outputs.gains.green;
    info.AWBGains.bGain = m_outputs.gains.blue;

    // Set pool color temperature
    info.colorTemperature = m_outputs.cct;

    return m_pNode->WriteDataList(WriteProps, pOutputData, pDataCount, CAMX_ARRAY_SIZE(WriteProps));
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::PublishToInternalMetadata
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::PublishToInternalMetadata()
{
    AWBOutputInternal output                                   = {};
    static const UINT WriteProps[]                             = {PropertyIDAWBInternal};
    const VOID*       pOutputData[CAMX_ARRAY_SIZE(WriteProps)] = { &output };
    UINT              pDataCount[CAMX_ARRAY_SIZE(WriteProps)]  = { sizeof(output) };

    // Set flash estimation status
    output.flashEstimationStatus = static_cast<AWBFlashEstimationState>(m_algoFlashEstimationState);

    // Set illuminant decision
    output.AWBDecision = static_cast<AWBIlluminant>(m_outputs.illuminantType);

    for (UINT32 sampleIndex = 0; sampleIndex < AWBDecisionMapSize; sampleIndex++)
    {
        output.AWBSampleDecision[sampleIndex] = static_cast<UINT8>(m_outputs.sampleDecision[sampleIndex]);
    }

    return m_pNode->WriteDataList(WriteProps, pOutputData, pDataCount, CAMX_ARRAY_SIZE(WriteProps));
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::PublishPropertyDebugData
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::PublishPropertyDebugData()
{
    CamxResult          result                      = CamxResultSuccess;
    UINT32              metaTag                     = 0;
    static const UINT   PropertiesDebugData[]       = { PropertyIDDebugDataAll };
    VOID*               pSrcData[1]                 = { 0 };
    UINT                length                      = CAMX_ARRAY_SIZE(PropertiesDebugData);
    UINT64              propertyDebugDataOffset[1]  = { 0 };

    // Make a copy in main metadata pool
    m_pNode->GetDataList(PropertiesDebugData, pSrcData, propertyDebugDataOffset, length);

    // Current framework implementation support only posting DebugDataAll
    result = VendorTagManager::QueryVendorTagLocation("org.quic.camera.debugdata", "DebugDataAll", &metaTag);
    if (CamxResultSuccess == result)
    {
        const UINT  DebugDataVendorTag[]    = { metaTag };
        const VOID* pDstData[1]             = { pSrcData[0] };
        UINT        pDataCount[1]           = { sizeof(DebugData) };
        result = m_pNode->WriteDataList(DebugDataVendorTag, pDstData, pDataCount, CAMX_ARRAY_SIZE(DebugDataVendorTag));
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::AllocateMemoryVendorTag
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::AllocateMemoryVendorTag(
    AWBAlgoGetParam* pAlgoGetParam)
{
    CAMX_ENTRYEXIT(CamxLogGroupAWB);
    CAMX_ASSERT_MESSAGE(NULL != pAlgoGetParam, "pAlgoGetParam NULL pointer");

    CamxResult              result          = CamxResultSuccess;
    AWBAlgoGetParamOutput*  pGetParamOutput =
        &pAlgoGetParam->outputInfoList.pGetParamOutputs[AWBGetParamOutputTypePublishingVendorTagsInfo];

    if (pGetParamOutput->sizeOfWrittenGetParamOutput > 0)
    {
        StatsVendorTagInfoList* pVendorTagInfoList = static_cast<StatsVendorTagInfoList*>(pGetParamOutput->pGetParamOutput);
        Utils::Memset(&m_outputs.vendorTagList, 0, sizeof(m_outputs.vendorTagList));
        for (UINT32 j = 0; j < pVendorTagInfoList->vendorTagCount; j++)
        {
            SIZE_T size = HAL3MetadataUtil::GetMaxSizeByTag(pVendorTagInfoList->vendorTag[j].vendorTagId);
            if (0 != size)
            {
                m_outputs.vendorTagList.vendorTag[j].vendorTagId = pVendorTagInfoList->vendorTag[j].vendorTagId;
                m_outputs.vendorTagList.vendorTag[j].appliedDelay = pVendorTagInfoList->vendorTag[j].appliedDelay;
                m_outputs.vendorTagList.vendorTag[j].pData = CAMX_CALLOC(size);

                if (NULL == m_outputs.vendorTagList.vendorTag[j].pData)
                {
                    CAMX_LOG_ERROR(CamxLogGroupAWB,
                        "Allocating memory for vendor tagID[%d]: %d failed.",
                        j,
                        pVendorTagInfoList->vendorTag[j].vendorTagId);
                    result = CamxResultENoMemory;
                }
                else
                {
                    m_outputs.vendorTagList.vendorTag[j].dataSize = static_cast<UINT32>(size);
                    m_outputs.vendorTagList.vendorTagCount++;
                }
            }
        }
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::GetDefaultBGConfig
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult CAWBIOUtil::GetDefaultBGConfig(
    StatsBayerGridBayerExposureConfig* pAWBBGConfigData
    ) const
{
    CamxResult result                       = CamxResultSuccess;
    const StaticSettings*   pStaticSettings = HwEnvironment::GetInstance()->GetStaticSettings();

    pAWBBGConfigData->horizontalRegionCount                     = BGConfigHorizontalRegions;
    pAWBBGConfigData->verticalRegionCount                       = BGConfigVerticalRegions;

    UINT32 bitShift = IFEPipelineBitWidth - BGStatsConsumpBitWidth;
    UINT32 satThreshold = BGConfigSaturationThreshold << bitShift;

    pAWBBGConfigData->channelGainThreshold[StatsColorChannelR] = satThreshold - 1;
    pAWBBGConfigData->channelGainThreshold[StatsColorChannelGR] = satThreshold - 1;
    pAWBBGConfigData->channelGainThreshold[StatsColorChannelGB] = satThreshold - 1;
    pAWBBGConfigData->channelGainThreshold[StatsColorChannelB] = satThreshold - 1;

    if ((TRUE == pStaticSettings->multiCameraEnable) && (MultiCamera3ASyncDisabled != pStaticSettings->multiCamera3ASync))
    {
        // Need to configure AWB based on croped window only for true zoom case
        // where anyway tele camera would have small FOV from where stats are generated
        // using croped stats avoid AWB flicker at time switching of camera.
        // and giving smooth change in AWB input
        // @todo (CAMX-3347): Croping should be done only in true zoom case, avoid in other case.
        if (m_setInputs.statsWindowInfo.cropWindow.left + m_setInputs.statsWindowInfo.cropWindow.width >
            m_setInputs.statsSensorInfo.sensorResWidth ||
            m_setInputs.statsWindowInfo.cropWindow.top + m_setInputs.statsWindowInfo.cropWindow.height >
            m_setInputs.statsSensorInfo.sensorResHeight)
        {
            CAMX_LOG_WARN(CamxLogGroupAWB, "Invalid crop Window (%d %d %d %d) lies outside of (0 0 %d %d)",
                m_setInputs.statsWindowInfo.cropWindow.left,
                m_setInputs.statsWindowInfo.cropWindow.top,
                m_setInputs.statsWindowInfo.cropWindow.width,
                m_setInputs.statsWindowInfo.cropWindow.height,
                m_setInputs.statsSensorInfo.sensorResWidth,
                m_setInputs.statsSensorInfo.sensorResHeight);
            // Even if wrong crop window is recieved do not overwrite input, because input is used in metadata
            // if wrong crop window configuring stats Window to IFE input resolution.
            pAWBBGConfigData->ROI.left   = 0;
            pAWBBGConfigData->ROI.top    = 0;
            pAWBBGConfigData->ROI.width  = m_setInputs.statsSensorInfo.sensorResWidth;
            pAWBBGConfigData->ROI.height = m_setInputs.statsSensorInfo.sensorResHeight;
        }
        else
        {
            pAWBBGConfigData->ROI.left   = m_setInputs.statsWindowInfo.cropWindow.left;
            pAWBBGConfigData->ROI.top    = m_setInputs.statsWindowInfo.cropWindow.top;
            pAWBBGConfigData->ROI.width  = m_setInputs.statsWindowInfo.cropWindow.width;
            pAWBBGConfigData->ROI.height = m_setInputs.statsWindowInfo.cropWindow.height;
        }
    }
    else
    {
        // Configuring stats to maximum resolution
        pAWBBGConfigData->ROI.left   = 0;
        pAWBBGConfigData->ROI.top    = 0;
        pAWBBGConfigData->ROI.width  = m_setInputs.statsSensorInfo.sensorResWidth;
        pAWBBGConfigData->ROI.height = m_setInputs.statsSensorInfo.sensorResHeight;
    }

    CAMX_LOG_VERBOSE(CamxLogGroupAWB, "Stats ROI(l:%d t:%d w:%d h:%d)",
                     pAWBBGConfigData->ROI.left,
                     pAWBBGConfigData->ROI.top,
                     pAWBBGConfigData->ROI.width,
                     pAWBBGConfigData->ROI.height);

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::InvalidateIO
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID CAWBIOUtil::InvalidateIO()
{
    UINT32 i = 0;

    for (i = 0; i < AWBInputTypeLastIndex; i++)
    {
        m_processInputArray[i].inputType = AWBInputTypeInvalid;
    }

    for (i = 0; i < AWBOutputTypeLastIndex; i++)
    {
        m_processOutputArray[i].outputType = AWBOutputTypeInvalid;
    }

    for (i = 0; i < AWBGetParamInputTypeLastIndex; i++)
    {
        m_getParamInputArray[i].getParamInputType = AWBGetParamInputTypeInvalid;
    }

    for (i = 0; i < AWBGetParamOutputTypeLastIndex; i++)
    {
        m_getParamOutputArray[i].getParamOutputType = AWBGetParamOutputTypeInvalid;
    }

    for (i = 0; i < AWBSetParamTypeLastIndex; i++)
    {
        m_setParamInputArray[i].setParamType = AWBSetParamTypeInvalid;
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::FillBGConfigurationData
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID CAWBIOUtil::FillBGConfigurationData(
    AWBConfig*                                  pAWBConfigData,
    const StatsBayerGridBayerExposureConfig*    pAWBAlgoConfig)
{
    CAMX_ASSERT(NULL != pAWBConfigData);
    CAMX_ASSERT(NULL != pAWBAlgoConfig);

    const StaticSettings* pStaticSettings = HwEnvironment::GetInstance()->GetStaticSettings();

    pAWBConfigData->BGConfig.horizontalNum                        = pAWBAlgoConfig->horizontalRegionCount;
    pAWBConfigData->BGConfig.verticalNum                          = pAWBAlgoConfig->verticalRegionCount;
    pAWBConfigData->BGConfig.channelGainThreshold[ChannelIndexR]  = pAWBAlgoConfig->channelGainThreshold[StatsColorChannelR];
    pAWBConfigData->BGConfig.channelGainThreshold[ChannelIndexGR] = pAWBAlgoConfig->channelGainThreshold[StatsColorChannelGR];
    pAWBConfigData->BGConfig.channelGainThreshold[ChannelIndexGB] = pAWBAlgoConfig->channelGainThreshold[StatsColorChannelGB];
    pAWBConfigData->BGConfig.channelGainThreshold[ChannelIndexB]  = pAWBAlgoConfig->channelGainThreshold[StatsColorChannelB];
    pAWBConfigData->BGConfig.outputBitDepth                       = pAWBAlgoConfig->outputBitDepth;
    pAWBConfigData->BGConfig.outputMode                           = BGBERegular;

    // Need to configure AWB based on croped window only for true zoom case or based on tuning parameter
    // where anyway tele camera would have small FOV from where stats are generated
    // using croped stats avoid AWB flicker at time switching of camera.
    // and giving smooth change in AWB input
    if (m_setInputs.statsWindowInfo.cropWindow.left + m_setInputs.statsWindowInfo.cropWindow.width >
        m_setInputs.statsSensorInfo.sensorResWidth ||
        m_setInputs.statsWindowInfo.cropWindow.top + m_setInputs.statsWindowInfo.cropWindow.height >
        m_setInputs.statsSensorInfo.sensorResHeight)
    {
        CAMX_LOG_WARN(CamxLogGroupAWB, "Invalid crop Window (%d %d %d %d) lies outside of (0 0 %d %d)",
                      m_setInputs.statsWindowInfo.cropWindow.left,
                      m_setInputs.statsWindowInfo.cropWindow.top,
                      m_setInputs.statsWindowInfo.cropWindow.width,
                      m_setInputs.statsWindowInfo.cropWindow.height,
                      m_setInputs.statsSensorInfo.sensorResWidth,
                      m_setInputs.statsSensorInfo.sensorResHeight);
        // Even if wrong crop window is recieved do not overwrite input, because input is used in metadata
        // if wrong crop window configuring stats Window to IFE input resolution.
        pAWBConfigData->BGConfig.ROI.left   = 0;
        pAWBConfigData->BGConfig.ROI.top    = 0;
        pAWBConfigData->BGConfig.ROI.width  = m_setInputs.statsSensorInfo.sensorResWidth;
        pAWBConfigData->BGConfig.ROI.height = m_setInputs.statsSensorInfo.sensorResHeight;
    }
    else
    {
        pAWBConfigData->BGConfig.ROI.left   = m_setInputs.statsWindowInfo.cropWindow.left;
        pAWBConfigData->BGConfig.ROI.top    = m_setInputs.statsWindowInfo.cropWindow.top;
        pAWBConfigData->BGConfig.ROI.width  = m_setInputs.statsWindowInfo.cropWindow.width;
        pAWBConfigData->BGConfig.ROI.height = m_setInputs.statsWindowInfo.cropWindow.height;

        if (StatsROISelectionFullFOV == pAWBAlgoConfig->ROISelection && (FALSE == pStaticSettings->multiCameraEnable))
        {
            pAWBConfigData->BGConfig.ROI.left   = 0;
            pAWBConfigData->BGConfig.ROI.top    = 0;
            pAWBConfigData->BGConfig.ROI.width  = m_setInputs.statsSensorInfo.sensorResWidth;
            pAWBConfigData->BGConfig.ROI.height = m_setInputs.statsSensorInfo.sensorResHeight;
        }
    }

    if ((CSLPresilEnabled == GetCSLMode()) || (CSLPresilRUMIEnabled == GetCSLMode()))
    {
        pAWBConfigData->BGConfig.ROI.left   = 0;
        pAWBConfigData->BGConfig.ROI.top    = 0;
        pAWBConfigData->BGConfig.ROI.width  = pStaticSettings->IFETestImageSizeWidth;
        pAWBConfigData->BGConfig.ROI.height = pStaticSettings->IFETestImageSizeHeight;
    }

    CAMX_LOG_VERBOSE(CamxLogGroupAWB, "Final BG Stats Config to IFE: HNUM:%d VNUM:%d CH_GainThr[R:%d GR:%d GB:%d B:%d] "
                     "O/P BitDepth:%d O/P Mode:%d ROI Selection:%d ROI:(l:%d t:%d w:%d h:%d)",
                     pAWBConfigData->BGConfig.horizontalNum,
                     pAWBConfigData->BGConfig.verticalNum,
                     pAWBConfigData->BGConfig.channelGainThreshold[ChannelIndexR],
                     pAWBConfigData->BGConfig.channelGainThreshold[ChannelIndexGR],
                     pAWBConfigData->BGConfig.channelGainThreshold[ChannelIndexGB],
                     pAWBConfigData->BGConfig.channelGainThreshold[ChannelIndexB],
                     pAWBConfigData->BGConfig.outputBitDepth,
                     pAWBConfigData->BGConfig.outputMode,
                     pAWBAlgoConfig->ROISelection,
                     pAWBConfigData->BGConfig.ROI.left,
                     pAWBConfigData->BGConfig.ROI.top,
                     pAWBConfigData->BGConfig.ROI.width,
                     pAWBConfigData->BGConfig.ROI.height);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::FillIlluminantCalibrationFactor
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID CAWBIOUtil::FillIlluminantCalibrationFactor(
    const WBCalibrationData*                pWBCalibrationData,
    AWBAlgoIlluminantsCalibrationFactor*    pIlluminantsCalibrationFactor)
{
    CAMX_ASSERT(NULL != pWBCalibrationData);
    UINT32 colorTemperature     = AWBAlgoColorTemperateD50;
    UINT32 calibrationDataCount = 0;

    for (UINT32 i = 0; i < MaxLightTypes; i++)
    {
        if (pWBCalibrationData[i].isAvailable)
        {
            switch (static_cast<EEPROMIlluminantType>(i))
            {
                case EEPROMIlluminantType::D65:
                    colorTemperature = AWBAlgoColorTemperateD65;
                    break;
                case EEPROMIlluminantType::TL84:
                    colorTemperature = AWBAlgoColorTemperateTL84;
                    break;
                case EEPROMIlluminantType::A:
                    colorTemperature = AWBAlgoColorTemperateIncandescent;
                    break;
                case EEPROMIlluminantType::D50:
                    colorTemperature = AWBAlgoColorTemperateD50;
                    break;
                case EEPROMIlluminantType::H:
                    colorTemperature = AWBAlgoColorTemperateHorizon;
                    break;
                default:
                    break;
            }
            pIlluminantsCalibrationFactor->illuminant[i].isAvailable = TRUE;
            pIlluminantsCalibrationFactor->illuminant[i].correlatedColorTemperature = colorTemperature;
            pIlluminantsCalibrationFactor->illuminant[i].ratioRG = pWBCalibrationData[i].rOverG;
            pIlluminantsCalibrationFactor->illuminant[i].ratioBG = pWBCalibrationData[i].bOverG;
            CAMX_LOG_VERBOSE(CamxLogGroupAWB, "colorTemperature: %d  ratioRG: %f  ratioBG: %f",
                             colorTemperature, pWBCalibrationData[i].rOverG, pWBCalibrationData[i].bOverG);
            calibrationDataCount++;
        }
    }

    pIlluminantsCalibrationFactor->numberOfIlluminants = calibrationDataCount;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CAWBIOUtil::~CAWBIOUtil
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CAWBIOUtil::~CAWBIOUtil()
{
    // Destroy all the created objects.
    // free memory allocated for holding vendor tag data
    for (UINT32 i = 0; i < m_outputs.vendorTagList.vendorTagCount; i++)
    {
        if (NULL != m_outputs.vendorTagList.vendorTag[i].pData)
        {
            CAMX_FREE(m_outputs.vendorTagList.vendorTag[i].pData);
            m_outputs.vendorTagList.vendorTag[i].pData = NULL;
        }
    }

}
CAMX_NAMESPACE_END
